using System.Collections.Generic;
using System.Reflection;
using System;

namespace HEFramework
{
    /// <summary>
    ///
    /// 代码持有器
    /// 
    /// ----------------------------------------
    /// 作者 hep
    /// 创建时间：2023-11-29 16:40:30
    /// ----------------------------------------
    /// </summary>
    public class CodeOwner : Singleton<CodeOwner>, ISingletonAwake<Assembly[]>
    {
        /// <summary>
        /// 程序集所有的类型
        /// </summary>
        private readonly Dictionary<string, Type> allTypes = new();

        /// <summary>
        /// 框架指定的类型
        /// </summary>
        private readonly UnOrderMultiMap_HashSet<Type, Type> types = new();

        public void Awake(Assembly[] _assemblies)
        {
            GetAssemblyTypes(_assemblies);
        }

        public Dictionary<string, Type> GetTypes()
        {
            return allTypes;
        }

        /// <summary>
        /// 获得框架规定的类型
        /// </summary>
        /// <param name="_type">打上CustomAttribute标签的类型可以获取到</param>
        /// <returns></returns>
        public HashSet<Type> GetTypes(Type _type)
        {
            if (!this.types.ContainsKey(_type))
            {
                return new HashSet<Type>();
            }

            return this.types[_type];
        }

        /// <summary>
        /// 获取某个类型
        /// </summary>
        /// <param name="_typeName"></param>
        /// <returns></returns>
        public Type GetType(string _typeName)
        {
            return this.allTypes[_typeName];
        }

        /// <summary>
        /// 所有打上Code标签的单例重新创建
        /// </summary>
        public void CreateCodeSingleton()
        {
            var hashSet = this.GetTypes(typeof(CodeAttribute));
            foreach (Type type in hashSet)
            {
                object obj = Activator.CreateInstance(type);
                ((ISingletonAwake)obj).Awake();
                World.Instance.AddSingleton((ASingleton)obj);
            }
        }

        /// <summary>
        /// 获得程序集类的类型
        /// </summary>
        /// <param name="_args"></param>
        private void GetAssemblyTypes(params Assembly[] _args)
        {
            foreach (Assembly ass in _args)
            {
                foreach (Type type in ass.GetTypes())
                {
                    allTypes[type.FullName] = type;
                }
            }

            foreach ((string fullName, Type type) in allTypes)
            {
                //抽象类返回
                if (type.IsAbstract)
                {
                    continue;
                }

                // 记录所有的有CustomAttribute标记的的类型
                object[] objects = type.GetCustomAttributes(typeof(CustomAttribute), true);

                foreach (object o in objects)
                {
                    this.types.Add(o.GetType(), type);
                }
            }
        }
    }
}